/*
 * Copyright (c) 2011 Ball State University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * NOTE:
 * Derivative work based on the Google IO 2011 Schedule app released for open source
 * http://code.google.com/p/iosched/
 */

package edu.bsu.android.gtv.apps.bconnected.ui;

import com.google.android.imageloader.ImageLoader;

import edu.bsu.android.gtv.apps.bconnected.R;
import edu.bsu.android.gtv.apps.bconnected.data.HousingData;
import edu.bsu.android.gtv.apps.bconnected.data.PersonData;
import edu.bsu.android.gtv.apps.bconnected.objects.Housing;
import edu.bsu.android.gtv.apps.bconnected.objects.Person;
import edu.bsu.android.gtv.apps.bconnected.ui.HomeActivity;
import edu.bsu.android.gtv.apps.bconnected.ui.base.BaseActivity;
import edu.bsu.android.gtv.apps.bconnected.util.Adapters;
import edu.bsu.android.gtv.apps.bconnected.util.AnalyticsUtils;
import edu.bsu.android.gtv.apps.bconnected.util.Constants;
import edu.bsu.android.gtv.apps.bconnected.util.LoginHelper;
import edu.bsu.android.gtv.apps.bconnected.util.UIUtils;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

/**
 * An activity that shows detail information for the student's on campus housing, including description, neighbors and living-learning 
 * community info.  Single activity pane that displays the housing information.
 * @author Kyle Parker, University Computing Services
 */
public class HousingInfoActivity extends BaseActivity {
    private static final String TAG = "HousingInfoActivity";
    private static final String TAG_DESCRIPTION = "desc";
    private static final String TAG_ROOMMATES = "roommates";
    private static final String TAG_LIVING_LEARNING = "living_learning";

    private TabHost mTabHost;
    private Housing mHousing;
    private View mLoadingSpinner;
    private View mRoommateSpinner;
    private Activity mActivity;
    private BroadcastReceiver mReceiver;
    
    private String mLoginGuid;
    private String mBSUID;
    private String mRoomID;
    private String mFloorCode;
    private String mHallCode;
    private String mBuildingDesc;
    private String mLatitude;
    private String mLongitude;
    private boolean mLogin;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_housing_info);
		
        getActivityHelper().setupActionBar(false, "My Home");        
        mActivity = this;
                
        handleLogout();    
        handleLogin();
                
        mTabHost = (TabHost) findViewById(android.R.id.tabhost);
       	mTabHost.setup();

        mLoadingSpinner = findViewById(R.id.loading_spinner); 
        mLoadingSpinner.setVisibility(View.VISIBLE); 
        
        mRoommateSpinner = findViewById(R.id.spinner_roommate);  
        mRoommateSpinner.setVisibility(View.VISIBLE);

        setupDescriptionTab();
        setupRoommatesTab();
        setupLivingLearningTab();

		// Hide the housing information while the data is loading
		hideHousingInfo();
		if (mLogin) {
			loadHousingInfo();
		}

		// Set the current tab to the last selection of the student - either the description or the neighbors
        mTabHost.setCurrentTab(UIUtils.getLastID(mActivity, Constants.PREF_HOUSING_TAB));
        // Reset the tab position
        UIUtils.setLastID(mActivity, Constants.PREF_HOUSING_TAB, 0);

        AnalyticsUtils.getInstance(mActivity).trackPageView("/HousingInfo");
    }
    
    @Override 
    public void onDestroy() {
    	super.onResume();
    	mActivity.unregisterReceiver(mReceiver);
    }

    /**
     * Using a new thread, separate from the main activity, load the housing information from the service handler
     */
    private void loadHousingInfo() {		
        Runnable load = new Runnable(){
            public void run() {
            	try {
	            	HousingData.initializeHousing(mBSUID, mLoginGuid, mActivity);
	            	
	            	if (HousingData.getHousingCount() > 0) {
	            		mHousing = HousingData.getHousing(0);

	            		if (mHousing.getImageURL() != null) {
		                    ImageLoader imageLoader = new ImageLoader();
		                    
		                    ImageView image = (ImageView) findViewById(R.id.building_photo);
		                    image.setTag(mHousing.getImageURL().toString());
		                    image.setContentDescription(mHousing.getComplexName());
		                    imageLoader.bind(image, mHousing.getImageURL().toString(), null);
	            		}
	            	}
	    	    	
	    	    	mActivity.runOnUiThread(returnHousing);
            	} catch (Exception ex) {        
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadHousingInfo");
        thread.start();
    }

    /**
     * Load the housing info from the service handler and set the visibility of the spinner to "gone"
     */
    private Runnable returnHousing = new Runnable(){
        public void run() {
        	// If the call to the housing service did not return the "error" attribute, then display the housing information, otherwise 
        	// the expiration date has expired for the user or they are not authorized under the current credentials to access the information.
        	// When retrieving data from the .NET service handler, the BSU ID and login guid are matched against the SQL Server database.  If
        	// the combination of the two do not match, then the user is not permitted to retrieve the requested data.  The guards against
        	// someone hacking the querystring parameters to retrieve the information of another student.
        	if (HousingData.getHousingAuth()) {
        		displayHousingInfo();
        	} else {
                findViewById(R.id.empty_housing_info_container).setVisibility(View.VISIBLE);
                ((TextView) findViewById(R.id.empty_housing_info)).setText(R.string.error_auth);
        	}
        	
            mLoadingSpinner.setVisibility(View.GONE);
        }
    };

    /**
     * Using a new thread, separate from the main activity, load the roommates/floormates from the service handler
     */
    private void loadRoommate() {			
        Runnable load = new Runnable(){
            public void run() { 
            	try {
                	PersonData.initializeRoommates(mBSUID, mRoomID, mFloorCode, mHallCode, mLoginGuid, mActivity);
        	    	
            		mActivity.runOnUiThread(returnRoommate);
            	} catch (Exception ex) {
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadRoommate");
        thread.start();
    }
    
    /**
     * Display the roomates in a separate thread
     */
    private Runnable returnRoommate = new Runnable(){
        public void run() {
        	// If the call to the housing service did not return the "error" attribute, then display the housing information, otherwise 
        	// the expiration date has expired for the user or they are not authorized under the current credentials to access the information.
        	// When retrieving data from the .NET service handler, the BSU ID and login guid are matched against the SQL Server database.  If
        	// the combination of the two do not match, then the user is not permitted to retrieve the requested data.  The guards against
        	// someone hacking the querystring parameters to retrieve the information of another student.
        	if (HousingData.getHousingAuth()) {
            	displayRoommates();
            	
                if (PersonData.getRoommateCount() == 0) {
                    TextView empty = ((TextView) findViewById(R.id.empty_roommates));
                    empty.setVisibility(View.VISIBLE);
                }
        	} 
        	
            mRoommateSpinner.setVisibility(View.GONE);
        }
    };
    
    /**
     * Display the housing information and show the roommates
     */
    private void displayHousingInfo() { 
    	if (mHousing != null) {
    		LinearLayout view = (LinearLayout) findViewById(R.id.housing_info_container);
            view.setVisibility(View.VISIBLE);
        	view.setBackgroundResource(R.color.content_background);
	        
			mBuildingDesc = mHousing.getComplexName();
			mLongitude = mHousing.getLongitude();
			mLatitude = mHousing.getLatitude();  
			mRoomID = mHousing.getRoomID();
			mFloorCode = mHousing.getFloorCode();
			mHallCode = mHousing.getHallCode();
	    	 
			if (Integer.parseInt(mHousing.getHousingType()) == Constants.VALUE_HOUSING_TYPE_HALL) {		    	
		    	loadRoommate();

		    	// TODO: Put the hall and room on separate lines
				UIUtils.displayTextView(view, R.id.hall_desc, mHousing.getHallDesc() + " " + mActivity.getString(R.string.content_hall)); 
				UIUtils.displayTextView(view, R.id.room, mActivity.getString(R.string.content_room) + " " + mHousing.getRoomNumber());
				UIUtils.displayTextView(view, R.id.room_type, mHousing.getRoomDesc() + " " + mActivity.getString(R.string.content_room) + " " + 
						mActivity.getString(R.string.content_on) + " " + mHousing.getFloorDesc().toLowerCase() + " " + 
						mActivity.getString(R.string.content_floor));
				UIUtils.displayTextView(view, R.id.complex_name, mActivity.getString(R.string.content_located) + " " + 
						mHousing.getHallGroupDesc() + " " + mActivity.getString(R.string.content_part_of) + " " + mHousing.getComplexName());
				UIUtils.displayTextView(view, R.id.contract_type, mHousing.getContractType() + " " + 
						mActivity.getString(R.string.content_contract) + " " + mHousing.getMealPlan());
				UIUtils.displayTextView(view, R.id.living_learning, mHousing.getLivingLearning());
			} else if (Integer.parseInt(mHousing.getHousingType()) == Constants.VALUE_HOUSING_TYPE_APARTMENT) {
				// Hide the roommates and living-learning tab for the apartment residents
				mTabHost.getTabWidget().getChildAt(1).setVisibility(View.GONE);
				mTabHost.getTabWidget().getChildAt(2).setVisibility(View.GONE);
				
				UIUtils.displayTextView(view, R.id.hall_desc, mHousing.getComplexName() + 
						mActivity.getString(R.string.content_apartment_number) + mHousing.getRoomNumber()); 
				UIUtils.displayTextView(view, R.id.room, mHousing.getRoomDesc());
				UIUtils.displayTextView(view, R.id.complex_name, mActivity.getString(R.string.content_located_at) + " " + 
						mHousing.getHallGroupDesc() + mActivity.getString(R.string.content_muncie));
			}

			UIUtils.displayTextView(view, R.id.housing_desc, mHousing.getComplexDesc());
			UIUtils.displayTextView(view, R.id.housing_features, mHousing.getComplexFeatures());
			
	    	// Display the standard map graphic and launch the Google Maps intent when tapped
	    	ImageView image = (ImageView) view.findViewById(R.id.campus_map);
	    	
	    	image.setImageResource(R.drawable.campus_map);
	    	image.setOnClickListener(new OnClickListener(){
				public void onClick(View v) {
	            	Intent intent = UIUtils.getGoogleMapsIntent(mBuildingDesc, mLatitude, mLongitude);
	            	
	            	if (intent != null) {
	            		startActivity(intent);
	            	} else {
	                    final String errorText = mActivity.getString(R.string.toast_error_location); 
	                    Toast.makeText(mActivity, errorText, Toast.LENGTH_LONG).show();
	            	}
				}
			});
    	} else {
    		hideHousingInfo();
    		((TextView) showEmptyHousingInfo().findViewById(R.id.empty_housing_info)).setText(R.string.empty_housing_info);
    	}
    }

    /**
     * Hide the housing view during the load process or if the housing object is empty
     */
    private void hideHousingInfo() {  
    	LinearLayout view = (LinearLayout) findViewById(R.id.housing_info_container);
        view.setVisibility(View.GONE);			
    }

    /**
     * Show the housing view during the load process or if the housing object is empty
     */
	private View showEmptyHousingInfo() {
		LinearLayout view = (LinearLayout) findViewById(R.id.empty_housing_info_container);
		view.setVisibility(View.VISIBLE);
        view.setBackgroundResource(R.drawable.empty_my_home);
        
        return view;
	}
    
    /**
     * Display the roomates/floormates for the student
     */
    private void displayRoommates() { 
    	if (PersonData.getRoommateCount() > 0) {
            Adapters.PersonAdapter adapter = new Adapters.PersonAdapter(mActivity, PersonData.getRoommates(), Constants.TARGET_ROOMMATE);
            
            final ListView lv = ((ListView) findViewById(R.id.roommates)); 
            lv.setAdapter(adapter); 
            lv.setOnItemClickListener(new OnItemClickListener(){
    			public void onItemClick(AdapterView<?> parentView, View childView, int position, long id) {
    		        final Intent intent = new Intent(Intent.ACTION_VIEW, null, mActivity, NeighborInfoActivity.class);

    		        Person person = (Person) lv.getItemAtPosition(position);
    		        
    		        intent.putExtra(Constants.EXTRA_BSU_ID, person.getBSUID());
    		        intent.putExtra(Constants.EXTRA_PERSON_TYPE_ID, person.getPersonType());

    		        UIUtils.setLastID(mActivity, Constants.PREF_HOUSING_TAB, 1); 

    		        mActivity.startActivity(intent);
    			}
    		});
    	}
    }
    
    /**
     * Build and add "description" tab.
     */
    private void setupDescriptionTab() {
        mTabHost.addTab(mTabHost.newTabSpec(TAG_DESCRIPTION)
                .setIndicator(UIUtils.buildIndicator(R.string.tab_description, mActivity))
                .setContent(R.id.tab_housing_desc));
    }
    
    /**
     * Build and add "roommates" tab.
     */
    private void setupRoommatesTab() {
        mTabHost.addTab(mTabHost.newTabSpec(TAG_ROOMMATES)
                .setIndicator(UIUtils.buildIndicator(R.string.tab_housing_roommates, mActivity))
                .setContent(R.id.tab_roommate));
    }
    
    /**
     * Build and add "living-learning" tab.
     */
    private void setupLivingLearningTab() {
        mTabHost.addTab(mTabHost.newTabSpec(TAG_LIVING_LEARNING)
                .setIndicator(UIUtils.buildIndicator(R.string.tab_living_learning, mActivity))
                .setContent(R.id.tab_living_learning));
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	MenuInflater inflater = new MenuInflater(this);
    	inflater.inflate(R.menu.map_menu_items, menu);
    	
    	super.onCreateOptionsMenu(menu);
        
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_map:
            	Intent intent = UIUtils.getGoogleMapsIntent(mBuildingDesc, mLatitude, mLongitude);
            	
            	if (intent != null) {
            		startActivity(intent);
            	} else {
                    final String errorText = mActivity.getString(R.string.toast_error_location); 
                    Toast.makeText(mActivity, errorText, Toast.LENGTH_LONG).show();
            	}
                return true;
        }
        
        return super.onOptionsItemSelected(item);
    }

    /**
     * In order to protect the activity from the back stack after a student logs out, remove the activity 
     * If the student hits the back button, this will take them to the Home activity
     */
    private void handleLogout() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Constants.ACTION_LOGOUT);
        mReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
		        intent = new Intent(Intent.ACTION_VIEW, null, mActivity, HomeActivity.class);
		        intent.putExtra(Constants.EXTRA_LOGIN_STATUS, Integer.toString(Constants.LOGIN_STATUS_LOGOUT));
		        
		        mActivity.startActivity(intent); 
			    mActivity.finish();
			}
		};
		
        mActivity.registerReceiver(mReceiver, intentFilter);
    }
    
    /**
     * Determine if the person has logged in and whether there is a person object in the database
     * Get the student's BSU ID for use throughout the application
     */
    private void handleLogin() {
    	Person person = LoginHelper.checkLogin(mActivity);
    	
    	if (person != null) {
    		mBSUID = person.getBSUID();
        	mLoginGuid = person.getLoginGuid();
        	
        	mLogin = true;
    	} else {
	        Intent intent = new Intent(Intent.ACTION_VIEW, null, mActivity, HomeActivity.class);
	        intent.putExtra(Constants.EXTRA_LOGIN_STATUS, Integer.toString(Constants.LOGIN_STATUS_NOT_LOGGED_IN));
	        
	        mActivity.startActivity(intent); 
	        mActivity.finish();
		    
		    mLogin = false;
    	}    	
    }
}
